package com.googlecode.pacswitch.conditions;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.AsynchronousSocketChannel;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

import com.googlecode.pacswitch.Condition;
import com.googlecode.pacswitch.ObjectFactory;
import com.googlecode.pacswitch.PInteger;
import com.googlecode.pacswitch.PString;
import com.googlecode.pacswitch.PacSwitch;

/**
 * @author Andrey Pavlenko
 */
@XmlType(name = "RequestPort", namespace = ObjectFactory.CNS)
public class RequestPort implements Condition {
    private PInteger _number;
    private PString _pattern;

    @XmlAttribute
    public PInteger getNumber() {
        return _number;
    }

    public void setNumber(final PInteger number) {
        _number = number;
    }

    @XmlAttribute
    public PString getPattern() {
        return _pattern;
    }

    public void setPattern(final PString pattern) {
        _pattern = pattern;
    }

    @Override
    public boolean apply(final PacSwitch ps,
            final AsynchronousSocketChannel clientSocket) {
        final PInteger number = getNumber();

        try {
            if (number != null) {
                final SocketAddress addr = clientSocket.getLocalAddress();

                if (addr instanceof InetSocketAddress) {
                    return ((InetSocketAddress) addr).getPort() == number
                            .resolveInt(ps, clientSocket);
                }
            } else {
                final PString pattern = getPattern();

                if (pattern != null) {
                    final SocketAddress addr = clientSocket.getLocalAddress();

                    if (addr instanceof InetSocketAddress) {
                        return String.valueOf(
                                ((InetSocketAddress) addr).getPort()).matches(
                                pattern.resolve(ps, clientSocket));
                    }
                } else {
                    ps.getConfig()
                            .getLog()
                            .warn("Neither number nor pattern attribute is specified");
                }
            }
        } catch (final IOException ex) {
            ps.getConfig().getLog().error("Error occurred", ex);
        }

        return false;
    }
}
